from fullsteam import json


LINE_COUNT = 5
LINE_WIDTH = 13
MIDDLE = LINE_WIDTH / 2
BASE = [None, None, None, None, None, None, None, None, None, None , None, None, None]


class Line(json.JSONable):
    _json_attrs = ('id', 'content')

    def __init__(self, id, content):
        if isinstance(content, list):
            assert len(content) == LINE_WIDTH, repr(content)
        self.id = id
        self.content = content

    def check_done(self, game):
        return True

    def __repr__(self):
        return '<%s id=%i>' % (self.__class__.__name__, self.id)


class Mountain(Line):
    def check_done(self, game):
        print 'mountain'
        for input in game.inputs:
            failed = []
            if not input.upside_down:
                failed.append(input.username)
            if failed:
                game.over('Next time: duck and cover, ' + ', '.join(failed))


class Log(Line):
    _json_attrs = ('id', 'content', 'health')

    """ A line with a log on the track"""
    def __init__(self, id, content):
        content[MIDDLE] = 'Baumstamm2'
        super(Log, self).__init__(id, content)
        self.health = 15

    def check_done(self, game):
        if self.health >= 0:
            game.over('Hello Tree!')


#class Crossing(Line):
#    _json_attrs = ('id', 'content', 'health')
#
#    """ A line with a log on the track"""
#    def __init__(self, id, content):
#        super(Crossing, self).__init__(id, content)
#        self.health = 10
#
#    def check_done(self, game):
#        return
#        if self.health >= 0:
#            game.over('Crossed a line on a rail crossing!')


class Turn(Line):
    def __init__(self, id, content, done, fail):
        super(Turn, self).__init__(id, content)
        self.done = done
        self.fail = fail
        self.health = 2


class Switch(Line):
    def check_done(self, game):
        return
        game.distribute_positions()
        import game
        game.write_viewers({"message": 'switch', 'duration': 5000})


class MapGenerator(object):
    def __init__(self, game, random):
        self.id = 0
        self.game = game
        self.random = random
        self.generator = self.start()
        self.next = self.generator.next

    def get(self, cls, *data):
        self.id += 1
        return cls(self.id, *data)

    def start(self):
        yield self.get(Line, BASE)
        yield self.get(Line, BASE)
        line = BASE[:]
        last_shake = 0
        last_swipe = 0
        while 42:
            yield self.get(Line, line)

            line = BASE[:]

            # deco tree
            if self.random.random() < 0.5:
                pos = self.random.randint(0, LINE_WIDTH - 2)
                if pos >= MIDDLE:
                    pos += 1
                line[pos] = 'baum1'

            # TASKS
            if not 'shake' in self.game.unstaffed:
                print 'since last', self.id - last_shake
                if self.id - last_shake > 5:
                    if self.random.random() <  (self.id - last_shake) / 10:
                        yield self.get(Log, line)
                        last_shake = self.id
            else:
                print 'MAP GEN no shaker', self.game.unstaffed

            #if not 'swipe' in self.game.unstaffed:
            #    if self.id - last_swipe > 5:
            #        if self.random.random() <  (self.id - last_swipe) / 10:
            #            yield self.get(Crossing, line)
            #            last_swipe = self.id
            #else:
            #    print 'MAP GEN no swipe',  self.game.unstaffed

            # berg
            if self.random.random() < 0.15:
                print 'MAP GEN -- MOUNTAIN'
                start = self.random.randint(0, MIDDLE-1)
                stop = self.random.randint(0, MIDDLE-1)
                yield self.get(Mountain, [None] * start \
                          + ['berg_rocks_links'] \
                          + ['berg_rocks'] * (MIDDLE-start-1) \
                          + ['berg_rocks_tunnel'] \
                          + ['berg_rocks'] * (stop) \
                          + ['berg_rocks_rechts'] \
                          + [None] * (LINE_WIDTH - start - stop - (MIDDLE-start-1) - 3))
                for i in xrange(self.random.randint(2, 5)):
                    # TODO add trees ontop of hills
                    yield self.get(Mountain, [None] * start \
                              + ['berg_grasberg_rechts'] \
                              + ['berg_grasberg'] * (MIDDLE-start-1) \
                              + ['berg_grasberg'] \
                              + ['berg_grasberg'] * (stop) \
                              + ['berg_gras_rechts'] \
                              + [None] * (LINE_WIDTH - start - stop - (MIDDLE-start-1) - 3))
                yield self.get(Switch, [None] * start \
                          + ['berg_grasberg_obenlinks'] \
                          + ['berg_grasberg_oben'] * (MIDDLE-start-1) \
                          + ['berg_grasberg_oben'] \
                          + ['berg_grasberg_oben'] * (stop) \
                          + ['berg_grasberg_obenrechts'] \
                          + [None] * (LINE_WIDTH - start - stop - (MIDDLE-start-1) - 3))
                for i in xrange(16):
                    yield self.get(Line, BASE[:])

            # forrest
            if self.random.random() < 0.5:
                print 'MAP GEN -- forrest'
                for i in xrange(self.random.randint(2, 6)): # length of forrest
                    line = BASE[:]
                    for i in xrange(self.random.randint(2, 6)):
                        pos = self.random.randint(0, LINE_WIDTH - 2)
                        if pos >= MIDDLE:
                            pos += 1
                        line[pos] = 'baum1'

            if self.id > 20 and not 'swipe' in self.game.unstaffed:
                 if self.random.random() < 0.5:
                    if self.random.random() < 0.5:
                        name = 'rechtskurve'
                        done = 'right'
                        fail = 'left'
                    else:
                        name = 'linkskurve'
                        done = 'left'
                        fail = 'right'
                    import game
                    game.write_viewers({"next_direction": fail})
                    yield self.get(Turn, name, done, fail)
                    for i in xrange(16):
                        # after turn we need some free lines, looks too awkward otherwise
                        yield self.get(Line, BASE[:])
